/**
 *
 * @author ozavadil
 */
package vladedivac;

import com.dukascopy.api.Configurable;
import com.dukascopy.api.IAccount;
import com.dukascopy.api.IBar;
import com.dukascopy.api.IConsole;
import com.dukascopy.api.IContext;
import com.dukascopy.api.IEngine;
import com.dukascopy.api.IHistory;
import com.dukascopy.api.IIndicators;
import com.dukascopy.api.IMessage;
import com.dukascopy.api.IOrder;
import com.dukascopy.api.IStrategy;
import com.dukascopy.api.ITick;
import com.dukascopy.api.Instrument;
import com.dukascopy.api.JFException;
import com.dukascopy.api.OfferSide;
import com.dukascopy.api.Period;
import com.dukascopy.api.impl.History;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;

public class VladeDivac implements IStrategy {
    private IEngine engine = null;
    private IIndicators indicators = null;
    private int tagCounter = 0;
    private double[] ma1 = new double[Instrument.values().length];
    private IConsole console;
    private IHistory history;
    
    private double[] Levels;
    
    @Configurable("Currency")
    public Instrument currencyInstrument = Instrument.EURUSD;
    
    @Configurable("Distance")
    public int Distance = 5;
    
    @Configurable("Amount")
    public double Amount = 0.001;
    
    @Configurable("StopLoss")
    public double StopLoss = 10;        

    @Override
    public void onStart(IContext context) throws JFException {
        engine = context.getEngine();
        indicators = context.getIndicators();
        this.console = context.getConsole();
        console.getOut().println("Started");
        history = context.getHistory();
        
        Levels = new double[7];
                
        Period period = Period.DAILY;
        
        int candlesBefore = 1;
        int candleAfter = 0;
        int shift = 1;        
        IBar prevBar = history.getBar(currencyInstrument, period, OfferSide.BID, 1); //previous bar/candle
        
        double[][] pivots = indicators.pivot(currencyInstrument, period, OfferSide.BID, 7, prevBar.getTime(), prevBar.getTime());
        
        Levels[0] = pivots[5][0];   //R3
        Levels[1] = pivots[3][0];   //R2
        Levels[2] = pivots[1][0];   //R1
        Levels[3] = pivots[0][0];   //Pivot        
        Levels[4] = pivots[2][0];   //S1
        Levels[5] = pivots[4][0];   //S2
        Levels[6] = pivots[6][0];   //S3
        
        for (int i = 0; i < Levels.length; i++) {
            Levels[i] = roundValue(Levels[i]);
        }
        
        double price = history.getLastTick(currencyInstrument).getBid();
        int currentLevel = locateCurrentLevel(price);
        cancelUnrealizedOrders();
        openPositionsUpAndLow(currentLevel);        
    }

    @Override
    public void onStop() throws JFException {
        for (IOrder order : engine.getOrders()) {
            order.close();
        }
        console.getOut().println("Stopped");
    }

    @Override
    public void onTick(Instrument instrument, ITick tick) throws JFException {

    }

    @Override
    public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) {
    }

    //count open positions
    protected int positionsTotal(Instrument instrument) throws JFException {
        int counter = 0;
        for (IOrder order : engine.getOrders(instrument)) {
            if (order.getState() == IOrder.State.FILLED) {
                counter++;
            }
        }
        return counter;
    }

    protected String getLabel(Instrument instrument) {
        String label = instrument.name();
        label = label.substring(0, 2) + label.substring(3, 5);
        label = label + (tagCounter++);
        label = label.toLowerCase();
        return label;
    }

    @Override
    public void onMessage(IMessage message) throws JFException {
        if (message.getType() == IMessage.Type.ORDER_CLOSE_OK) {
            int currentLevel = locateCurrentLevel(message.getOrder().getClosePrice());
            cancelUnrealizedOrders();
            openPositionsUpAndLow(currentLevel);
        }
    }

    @Override
    public void onAccount(IAccount account) throws JFException {
    }
    
    private int locateCurrentLevel(double value) {
        int level = 0;
        while (value<Levels[level] && level < Levels.length)
            level++;
        return level;
    }
    
    private void openPositionsUpAndLow(int level) throws JFException {
        if (level >= 1 && level < Levels.length)         //Aktualni hladina je nad urovni povotu
        {
            double sellPrice = roundValue(Levels[level - 1] - Distance*currencyInstrument.getPipValue());
            double sellStopLoss = roundValue(sellPrice + StopLoss*currencyInstrument.getPipValue());
            double sellTakeProfit = roundValue(Levels[level] + Distance*currencyInstrument.getPipValue());
            double buyPrice = roundValue(Levels[level] + Distance*currencyInstrument.getPipValue());
            double buyStopLoss = roundValue(buyPrice - StopLoss*currencyInstrument.getPipValue());
            double buyTakeProfit = roundValue(Levels[level] - Distance*currencyInstrument.getPipValue());
            createOrder(sellPrice, IEngine.OrderCommand.SELL, sellStopLoss, sellTakeProfit);
            createOrder(buyPrice, IEngine.OrderCommand.BUY, buyStopLoss, buyTakeProfit);
        }
    }
    
    private void createOrder(double price, IEngine.OrderCommand orderCommand, double stopLoss, double takeProfit) throws JFException {
        String label = getLabel(currencyInstrument);
        IOrder order = engine.submitOrder(label, currencyInstrument, orderCommand, Amount, price, 0, stopLoss, takeProfit);
    }
    
    private void cancelUnrealizedOrders() throws JFException {
        for (IOrder o : engine.getOrders(currencyInstrument)) {            
            if (o.getState().equals(IOrder.State.CREATED))
                o.close();
        }
    }
    
    double roundValue(double d) {  
      DecimalFormatSymbols format = new DecimalFormatSymbols();
      format.setDecimalSeparator('.');
      DecimalFormat twoDForm = new DecimalFormat("#.#####", format);
      String roundedStr = twoDForm.format(d);
      double rounded = Double.valueOf(roundedStr);
      return rounded;
    }   
}